👤 Step 5: User Module – Low Level Design (LLD)
This document outlines the low-level implementation details of the user feature module in the Angular e-commerce frontend.
📦 Module Structure
src/
├── app/
│ └── features/
│ └── user/
│ ├── components/
│ │ ├── dashboard/
│ │ ├── profile/
│ │ ├── address-book/
│ │ └── settings/
│ ├── services/
│ │ └── user.service.ts
│ ├── store/
│ │ ├── user.actions.ts
│ │ ├── user.reducer.ts
│ │ ├── user.effects.ts
│ │ └── user.selectors.ts
│ ├── models/
│ │ └── user.model.ts
│ ├── user-routing.module.ts
│ └── user.module.ts
🧱 Component Breakdown
🏠 UserDashboardComponent
- Displays user overview: recent orders, profile link, address link
- Reuses
OrderSummaryComponent(from orders module)
🙍 ProfileComponent
- Reactive form with
name,email,phone - Loads/saves profile data from NgRx store
- Shows toast/snackbar after save
📦 AddressListComponent
- List user addresses
- Edit/delete/add actions (opens
AddressFormComponent)
📝 AddressFormComponent
- Reactive form for address fields
- Used in both add/edit mode
- Emits output to parent on save
🧪 Service: UserService
Handles API interaction for profile and address operations.
@Injectable({ providedIn: "root" })
export class UserService {
constructor(private http: HttpClient) {}
getProfile(): Observable<User> {
return this.http.get<User>("/api/user/profile");
}
updateProfile(profile: Partial<User>): Observable<User> {
return this.http.put<User>("/api/user/profile", profile);
}
getAddresses(): Observable<Address[]> {
return this.http.get<Address[]>("/api/user/addresses");
}
addAddress(addr: Address): Observable<Address> {
return this.http.post<Address>("/api/user/addresses", addr);
}
updateAddress(addr: Address): Observable<Address> {
return this.http.put<Address>(`/api/user/addresses/${addr.id}`, addr);
}
deleteAddress(id: string): Observable<void> {
return this.http.delete<void>(`/api/user/addresses/${id}`);
}
}
🧩 NgRx Store (optional)
✅ Actions – user.actions.ts
export const loadUserProfile = createAction("[User] Load Profile");
export const loadUserProfileSuccess = createAction(
"[User] Load Profile Success",
props<{ user: User }>()
);
export const updateUserProfile = createAction(
"[User] Update Profile",
props<{ profile: Partial<User> }>()
);
🔁 Reducer – user.reducer.ts
Updates profile data, addresses, loading flags.
🌐 Effects – user.effects.ts
Handles async API calls like loading profile, updating address.
🔍 Selectors – user.selectors.ts
export const selectUser = createSelector(
selectUserState,
(state) => state.profile
);
export const selectAddresses = createSelector(
selectUserState,
(state) => state.addresses
);
🔄 API Contracts
| Endpoint | Method | Request Body | Response |
|---|---|---|---|
/user/profile |
GET | – | User |
/user/profile |
PUT | Partial<User> |
User |
/user/addresses |
GET | – | Address[] |
/user/addresses |
POST | Address |
Address |
/user/addresses/:id |
PUT | Address |
Address |
/user/addresses/:id |
DELETE | – | void |
📐 Models
export interface User {
id: string;
name: string;
email: string;
phone?: string;
}
export interface Address {
id?: string;
fullName: string;
street: string;
city: string;
state: string;
zip: string;
country: string;
phone: string;
}
🚦 Routing & Guards
const routes: Routes = [
{
path: "dashboard",
component: UserDashboardComponent,
canActivate: [AuthGuard],
},
{ path: "profile", component: ProfileComponent, canActivate: [AuthGuard] },
{
path: "addresses",
component: AddressListComponent,
canActivate: [AuthGuard],
},
{ path: "settings", component: SettingsComponent, canActivate: [AuthGuard] },
];
🔐 Security & UX
- Use
AuthGuardon all user routes - Validate address form fields
- Show confirmation before deleting address
- Use snackbar for all actions (success/error)
✅ Responsibilities Summary
| Part | Responsibility |
|---|---|
UserDashboard |
Overview page |
ProfileComponent |
Edit user profile |
AddressListComponent |
View/manage addresses |
AddressFormComponent |
Add/edit address (modal or inline) |
UserService |
Backend API integration |
Store (NgRx) |
Profile and address state management |